using System.Text.Json;
using Microsoft.Extensions.Logging;
using CollabApp.Application.DTOs;
using CollabApp.Application.Interfaces;
using CollabApp.Domain.Services.Game;
using CollabApp.Domain.Entities.Game;

namespace CollabApp.Application.Services.Game;

/// <summary>
/// 游戏结果服务实现
/// 负责计算游戏结果、排名、奖励分配和成就解锁
/// </summary>
public class GameResultService : IGameResultService
{
    private readonly IRedisService _redisService;
    private readonly ILogger<GameResultService> _logger;
    
    private const string GAME_RESULT_KEY = "game_result:{0}";
    private const string PLAYER_STATISTICS_KEY = "player_stats:{0}:{1}";
    private const string GAME_STATISTICS_KEY = "game_stats:{0}";
    private const string PLAYER_RANKINGS_KEY = "rankings:{0}";

    public GameResultService(
        IRedisService redisService,
        ILogger<GameResultService> logger)
    {
        _redisService = redisService ?? throw new ArgumentNullException(nameof(redisService));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// 计算游戏最终结果
    /// 基于游戏类型和规则，计算所有玩家的最终成绩和排名
    /// </summary>
    public async Task<GameResult> CalculateGameResultAsync(Guid gameId)
    {
        try
        {
            _logger.LogInformation("计算游戏最终结果 - 游戏ID: {GameId}", gameId);

            // 获取游戏基础信息
            var gameInfoKey = $"game_info:{gameId}";
            var gameInfoJson = await _redisService.StringGetAsync(gameInfoKey);
            
            var gameResult = new GameResult
            {
                GameId = gameId,
                StartTime = DateTime.UtcNow.AddHours(-1), // 简化实现
                EndTime = DateTime.UtcNow,
                Duration = TimeSpan.FromHours(1),
                GameType = GameType.Territory, // 默认领地游戏
                EndReason = GameEndReason.Completed,
                PlayerResults = new List<PlayerResult>(),
                Statistics = new GameStatistics(),
                Metadata = new Dictionary<string, object>()
            };

            // 计算玩家排名和结果
            var rankings = await CalculatePlayerRankingsAsync(gameId);
            
            foreach (var ranking in rankings)
            {
                var playerResult = new PlayerResult
                {
                    PlayerId = ranking.PlayerId,
                    PlayerName = ranking.PlayerName,
                    FinalScore = ranking.Score,
                    Rank = ranking.Rank,
                    PlayTime = TimeSpan.FromHours(1), // 简化实现
                    IsWinner = ranking.Rank == 1,
                    Statistics = await CalculatePlayerStatisticsAsync(gameId, ranking.PlayerId),
                    AchievementsUnlocked = await CheckAchievementUnlocksAsync(gameId, ranking.PlayerId),
                    ExperienceGained = await CalculateExperienceRewardAsync(gameId, ranking.PlayerId),
                    ScoreGained = await CalculateScoreRewardAsync(gameId, ranking.PlayerId),
                    RatingChange = await CalculateRatingChangeAsync(gameId, ranking.PlayerId)
                };

                gameResult.PlayerResults.Add(playerResult);
            }

            // 生成游戏统计信息
            gameResult.Statistics = await GenerateGameStatisticsAsync(gameId);

            _logger.LogInformation("游戏结果计算完成 - 游戏ID: {GameId}, 玩家数: {PlayerCount}", 
                gameId, gameResult.PlayerResults.Count);

            return gameResult;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "计算游戏结果失败 - 游戏ID: {GameId}", gameId);
            throw;
        }
    }

    /// <summary>
    /// 计算玩家排名
    /// 根据得分、完成时间等因素确定玩家排名
    /// </summary>
    public async Task<List<PlayerRanking>> CalculatePlayerRankingsAsync(Guid gameId)
    {
        try
        {
            _logger.LogInformation("计算玩家排名 - 游戏ID: {GameId}", gameId);

            var rankings = new List<PlayerRanking>();

            // 从Redis获取所有玩家的游戏数据
            var gameConnectionsKey = $"game_connections:{gameId}";
            var connections = await _redisService.GetHashAllAsync(gameConnectionsKey);

            foreach (var connection in connections)
            {
                if (Guid.TryParse(connection.Value, out var playerId))
                {
                    // 获取玩家统计数据（简化实现，实际应从更详细的数据源获取）
                    var score = await CalculatePlayerFinalScore(gameId, playerId);
                    var territoryArea = await GetPlayerTerritoryArea(gameId, playerId);

                    var ranking = new PlayerRanking
                    {
                        PlayerId = playerId,
                        PlayerName = $"Player_{playerId.ToString()[..8]}", // 简化实现
                        Rank = 1, // 暂时设为1，后续会重新排序
                        Score = score,
                        TerritoryPercentage = (float)territoryArea,
                        KillCount = await GetPlayerKillCount(gameId, playerId),
                        DeathCount = await GetPlayerDeathCount(gameId, playerId),
                        SurvivalTime = TimeSpan.FromMinutes(45) // 简化实现
                    };

                    rankings.Add(ranking);
                }
            }

            // 按分数降序排序并分配排名
            rankings = rankings.OrderByDescending(r => r.Score)
                             .ThenByDescending(r => r.TerritoryPercentage)
                             .ThenBy(r => r.DeathCount)
                             .ToList();

            for (int i = 0; i < rankings.Count; i++)
            {
                rankings[i].Rank = i + 1;
            }

            // 缓存排名结果
            var rankingsKey = string.Format(PLAYER_RANKINGS_KEY, gameId);
            await _redisService.StringSetAsync(rankingsKey, JsonSerializer.Serialize(rankings), 
                TimeSpan.FromHours(24));

            _logger.LogInformation("玩家排名计算完成 - 游戏ID: {GameId}, 玩家数: {Count}", 
                gameId, rankings.Count);

            return rankings;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "计算玩家排名失败 - 游戏ID: {GameId}", gameId);
            return new List<PlayerRanking>();
        }
    }

    /// <summary>
    /// 计算经验值奖励
    /// 基于游戏表现和排名计算玩家获得的经验值
    /// </summary>
    public async Task<ExperienceReward> CalculateExperienceRewardAsync(Guid gameId, Guid playerId)
    {
        try
        {
            _logger.LogDebug("计算经验值奖励 - 游戏ID: {GameId}, 玩家ID: {PlayerId}", gameId, playerId);

            var ranking = await GetPlayerRanking(gameId, playerId);
            var statistics = await CalculatePlayerStatisticsAsync(gameId, playerId);

            // 基础经验值计算
            var baseExp = 100;
            var rankBonus = Math.Max(0, 5 - ranking.Rank) * 20; // 排名奖励
            var performanceBonus = (int)(statistics.TerritoryControlled * 10); // 表现奖励
            var timeBonus = 50; // 时间奖励

            var totalExp = baseExp + rankBonus + performanceBonus + timeBonus;

            var reward = new ExperienceReward
            {
                BaseExperience = baseExp,
                BonusExperience = rankBonus + performanceBonus + timeBonus + 25, // 合并所有奖励
                TotalExperience = totalExp,
                Sources = new List<ExperienceSource>
                {
                    new ExperienceSource { Source = "Base", Amount = baseExp, Description = "参与游戏基础奖励" },
                    new ExperienceSource { Source = "Rank", Amount = rankBonus, Description = $"排名第{ranking.Rank}位奖励" },
                    new ExperienceSource { Source = "Performance", Amount = performanceBonus, Description = "表现奖励" },
                    new ExperienceSource { Source = "Time", Amount = timeBonus, Description = "游戏时长奖励" }
                },
                LevelBefore = 1, // 简化实现
                LevelAfter = 1,
                LeveledUp = false
            };

            _logger.LogDebug("经验值奖励计算完成 - 玩家ID: {PlayerId}, 总经验: {TotalExp}", 
                playerId, totalExp);

            return reward;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "计算经验值奖励失败 - 游戏ID: {GameId}, 玩家ID: {PlayerId}", gameId, playerId);
            return new ExperienceReward();
        }
    }

    /// <summary>
    /// 计算积分奖励
    /// 基于游戏结果计算玩家获得的积分
    /// </summary>
    public async Task<ScoreReward> CalculateScoreRewardAsync(Guid gameId, Guid playerId)
    {
        try
        {
            _logger.LogDebug("计算积分奖励 - 游戏ID: {GameId}, 玩家ID: {PlayerId}", gameId, playerId);

            var ranking = await GetPlayerRanking(gameId, playerId);
            var statistics = await CalculatePlayerStatisticsAsync(gameId, playerId);

            // 基础积分计算
            var baseScore = 50;
            var rankMultiplier = Math.Max(0.5, 2.0 - (ranking.Rank - 1) * 0.3); // 排名系数
            var performanceScore = statistics.ActionsPerformed * 2;
            var bonusScore = ranking.Rank == 1 ? 100 : (ranking.Rank <= 3 ? 50 : 0); // 胜利奖励

            var totalScore = (int)((baseScore + performanceScore) * rankMultiplier) + bonusScore;

            var reward = new ScoreReward
            {
                BaseScore = baseScore,
                BonusScore = bonusScore + performanceScore + (int)(baseScore * (rankMultiplier - 1)), // 合并奖励
                TotalScore = totalScore,
                Multiplier = (float)rankMultiplier,
                Sources = new List<ScoreSource>
                {
                    new ScoreSource { Source = "Base", Amount = baseScore, Description = "基础积分" },
                    new ScoreSource { Source = "Performance", Amount = performanceScore, Description = "表现积分" },
                    new ScoreSource { Source = "Rank", Amount = (int)(baseScore * (rankMultiplier - 1)), Description = "排名加成" },
                    new ScoreSource { Source = "Bonus", Amount = bonusScore, Description = "奖励积分" }
                }
            };

            _logger.LogDebug("积分奖励计算完成 - 玩家ID: {PlayerId}, 总积分: {TotalScore}", 
                playerId, totalScore);

            return reward;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "计算积分奖励失败 - 游戏ID: {GameId}, 玩家ID: {PlayerId}", gameId, playerId);
            return new ScoreReward();
        }
    }

    /// <summary>
    /// 检查成就解锁
    /// 检查玩家在游戏中是否达成了特定成就
    /// </summary>
    public async Task<List<Achievement>> CheckAchievementUnlocksAsync(Guid gameId, Guid playerId)
    {
        try
        {
            _logger.LogDebug("检查成就解锁 - 游戏ID: {GameId}, 玩家ID: {PlayerId}", gameId, playerId);

            var achievements = new List<Achievement>();
            var statistics = await CalculatePlayerStatisticsAsync(gameId, playerId);
            var ranking = await GetPlayerRanking(gameId, playerId);

            // 胜利成就
            if (ranking.Rank == 1)
            {
                achievements.Add(new Achievement
                {
                    Id = "victory_royale",
                    Name = "胜利",
                    Description = "在游戏中获得第一名",
                    Type = AchievementType.Combat, // 使用可用的枚举值
                    Points = 300, // 使用Points而不是ExperienceReward/ScoreReward
                    UnlockedAt = DateTime.UtcNow,
                    Criteria = new Dictionary<string, object>
                    {
                        { "rank", 1 },
                        { "experience", 200 },
                        { "score", 100 }
                    }
                });
            }

            // 领地控制成就
            if (statistics.TerritoryControlled >= 50.0)
            {
                achievements.Add(new Achievement
                {
                    Id = "territory_master",
                    Name = "领地大师",
                    Description = "控制超过50%的地图领土",
                    Type = AchievementType.Territory,
                    Points = 225,
                    UnlockedAt = DateTime.UtcNow,
                    Criteria = new Dictionary<string, object>
                    {
                        { "territory_percentage", statistics.TerritoryControlled },
                        { "experience", 150 },
                        { "score", 75 }
                    }
                });
            }

            // 生存成就
            if (statistics.TimeAlive.TotalMinutes >= 45)
            {
                achievements.Add(new Achievement
                {
                    Id = "survivor",
                    Name = "幸存者",
                    Description = "在游戏中生存超过45分钟",
                    Type = AchievementType.Survival,
                    Points = 150,
                    UnlockedAt = DateTime.UtcNow,
                    Criteria = new Dictionary<string, object>
                    {
                        { "survival_time", statistics.TimeAlive.TotalMinutes },
                        { "experience", 100 },
                        { "score", 50 }
                    }
                });
            }

            // 高分成就
            if (ranking.Score >= 1000)
            {
                achievements.Add(new Achievement
                {
                    Id = "high_scorer",
                    Name = "高分玩家",
                    Description = "在单局游戏中获得1000分以上",
                    Type = AchievementType.Special, // 使用Special而不是Score
                    Points = 180,
                    UnlockedAt = DateTime.UtcNow,
                    Criteria = new Dictionary<string, object>
                    {
                        { "score", ranking.Score },
                        { "experience", 120 },
                        { "score_reward", 60 }
                    }
                });
            }

            _logger.LogDebug("成就检查完成 - 玩家ID: {PlayerId}, 解锁成就数: {Count}", 
                playerId, achievements.Count);

            return achievements;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "检查成就解锁失败 - 游戏ID: {GameId}, 玩家ID: {PlayerId}", gameId, playerId);
            return new List<Achievement>();
        }
    }

    /// <summary>
    /// 生成游戏统计报告
    /// 创建详细的游戏数据统计报告
    /// </summary>
    public async Task<GameStatisticsReport> GenerateStatisticsReportAsync(Guid gameId)
    {
        try
        {
            _logger.LogInformation("生成游戏统计报告 - 游戏ID: {GameId}", gameId);

            var rankings = await CalculatePlayerRankingsAsync(gameId);
            var topPerformer = rankings.FirstOrDefault();

            var report = new GameStatisticsReport
            {
                GameId = gameId,
                GeneratedAt = DateTime.UtcNow,
                GameDuration = TimeSpan.FromHours(1), // 简化实现
                TotalPlayers = rankings.Count,
                TotalActions = rankings.Sum(r => r.Score / 10), // 简化计算
                ActionBreakdown = new Dictionary<string, int>
                {
                    { "Move", 500 },
                    { "Attack", 150 },
                    { "Collect", 100 },
                    { "Skill", 80 }
                },
                TopPerformer = topPerformer != null ? 
                    await CalculatePlayerStatisticsAsync(gameId, topPerformer.PlayerId) : 
                    new PlayerStatistics(),
                KeyEvents = await GetGameKeyEvents(gameId),
                CustomMetrics = new Dictionary<string, object>
                {
                    { "AverageScore", rankings.Any() ? rankings.Average(r => r.Score) : 0 },
                    { "MaxTerritoryControl", rankings.Any() ? rankings.Max(r => r.TerritoryPercentage) : 0 },
                    { "TotalKills", rankings.Sum(r => r.KillCount) },
                    { "GameMode", "Territory" }
                }
            };

            _logger.LogInformation("统计报告生成完成 - 游戏ID: {GameId}", gameId);

            return report;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "生成统计报告失败 - 游戏ID: {GameId}", gameId);
            return new GameStatisticsReport { GameId = gameId, GeneratedAt = DateTime.UtcNow };
        }
    }

    /// <summary>
    /// 计算玩家评级变化
    /// 基于游戏结果更新玩家的技能评级
    /// </summary>
    public async Task<RatingChange> CalculateRatingChangeAsync(Guid gameId, Guid playerId)
    {
        try
        {
            _logger.LogDebug("计算评级变化 - 游戏ID: {GameId}, 玩家ID: {PlayerId}", gameId, playerId);

            var ranking = await GetPlayerRanking(gameId, playerId);
            var statistics = await CalculatePlayerStatisticsAsync(gameId, playerId);

            // 简化的评级计算系统
            var currentRating = 1200; // 默认评级
            var kFactor = 32; // K因子
            var expectedScore = 0.5; // 预期得分（简化）
            var actualScore = ranking.Rank == 1 ? 1.0 : (ranking.Rank <= 3 ? 0.7 : 0.3);

            var ratingChange = (int)(kFactor * (actualScore - expectedScore));
            var newRating = Math.Max(100, Math.Min(3000, currentRating + ratingChange));

            // 确定评级等级
            var newTier = newRating switch
            {
                >= 2500 => RatingTier.Master,
                >= 2000 => RatingTier.Diamond,
                >= 1500 => RatingTier.Platinum,
                >= 1000 => RatingTier.Gold,
                >= 600 => RatingTier.Silver,
                _ => RatingTier.Bronze
            };

            var change = new RatingChange
            {
                RatingBefore = currentRating,
                RatingAfter = newRating,
                Change = ratingChange,
                TierBefore = RatingTier.Silver, // 简化实现
                TierAfter = newTier,
                TierChanged = newTier != RatingTier.Silver,
                Reason = $"游戏结果：第{ranking.Rank}名"
            };

            _logger.LogDebug("评级变化计算完成 - 玩家ID: {PlayerId}, 评级变化: {Delta}", 
                playerId, ratingChange);

            return change;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "计算评级变化失败 - 游戏ID: {GameId}, 玩家ID: {PlayerId}", gameId, playerId);
            return new RatingChange();
        }
    }

    /// <summary>
    /// 保存游戏结果到历史记录
    /// 将游戏结果持久化到数据库
    /// </summary>
    public async Task<bool> SaveGameResultAsync(GameResult gameResult)
    {
        try
        {
            _logger.LogInformation("保存游戏结果 - 游戏ID: {GameId}", gameResult.GameId);

            var resultKey = string.Format(GAME_RESULT_KEY, gameResult.GameId);
            var serializedResult = JsonSerializer.Serialize(gameResult);

            // 保存到Redis，24小时过期
            await _redisService.StringSetAsync(resultKey, serializedResult, TimeSpan.FromHours(24));

            // 保存玩家统计数据
            foreach (var playerResult in gameResult.PlayerResults)
            {
                var statsKey = string.Format(PLAYER_STATISTICS_KEY, gameResult.GameId, playerResult.PlayerId);
                var serializedStats = JsonSerializer.Serialize(playerResult.Statistics);
                await _redisService.StringSetAsync(statsKey, serializedStats, TimeSpan.FromHours(24));
            }

            _logger.LogInformation("游戏结果保存成功 - 游戏ID: {GameId}", gameResult.GameId);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "保存游戏结果失败 - 游戏ID: {GameId}", gameResult.GameId);
            return false;
        }
    }

    /// <summary>
    /// 获取历史游戏结果
    /// 检索指定游戏的历史结果数据
    /// </summary>
    public async Task<GameResult?> GetGameResultAsync(Guid gameId)
    {
        try
        {
            _logger.LogDebug("获取游戏结果 - 游戏ID: {GameId}", gameId);

            var resultKey = string.Format(GAME_RESULT_KEY, gameId);
            var serializedResult = await _redisService.StringGetAsync(resultKey);

            if (string.IsNullOrEmpty(serializedResult))
            {
                _logger.LogWarning("未找到游戏结果 - 游戏ID: {GameId}", gameId);
                return null;
            }

            var gameResult = JsonSerializer.Deserialize<GameResult>(serializedResult);
            _logger.LogDebug("游戏结果获取成功 - 游戏ID: {GameId}", gameId);

            return gameResult;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取游戏结果失败 - 游戏ID: {GameId}", gameId);
            return null;
        }
    }

    /// <summary>
    /// 计算团队奖励
    /// 为团队游戏计算额外的团队协作奖励
    /// </summary>
    public async Task<TeamReward> CalculateTeamRewardAsync(Guid gameId, Guid teamId)
    {
        try
        {
            _logger.LogDebug("计算团队奖励 - 游戏ID: {GameId}, 团队ID: {TeamId}", gameId, teamId);

            // 简化的团队奖励实现
            var teamReward = new TeamReward
            {
                TeamId = teamId,
                BaseReward = 200,
                CooperationBonus = 150, // 包含原来的CooperationBonus + SynergyBonus
                TotalReward = 350,
                MemberRewards = new List<TeamMemberReward>() // 空列表，实际应填充
            };

            await Task.CompletedTask; // 避免编译器警告

            _logger.LogDebug("团队奖励计算完成 - 团队ID: {TeamId}, 总奖励: {TotalReward}", 
                teamId, teamReward.TotalReward);

            return teamReward;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "计算团队奖励失败 - 游戏ID: {GameId}, 团队ID: {TeamId}", gameId, teamId);
            return new TeamReward { TeamId = teamId };
        }
    }

    #region 私有辅助方法

    private async Task<PlayerRanking> GetPlayerRanking(Guid gameId, Guid playerId)
    {
        var rankings = await CalculatePlayerRankingsAsync(gameId);
        return rankings.FirstOrDefault(r => r.PlayerId == playerId) ?? new PlayerRanking { PlayerId = playerId, Rank = 999 };
    }

    private async Task<PlayerStatistics> CalculatePlayerStatisticsAsync(Guid gameId, Guid playerId)
    {
        try
        {
            // 简化的统计数据计算，只使用PlayerStatistics中实际存在的属性
            await Task.CompletedTask; // 避免编译器警告
            
            return new PlayerStatistics
            {
                PlayerId = playerId,
                ActionsPerformed = 250,
                KillCount = 8,
                DeathCount = 2,
                TerritoryControlled = 25.5f,
                MaxTerritoryControlled = 35.0f,
                ItemsCollected = 12,
                SkillsUsed = 8,
                DistanceTraveled = 2340.6f,
                TimeAlive = TimeSpan.FromMinutes(42),
                DetailedStats = new Dictionary<string, int>
                {
                    { "TerritoryExpansions", 15 },
                    { "DefensiveActions", 22 },
                    { "PowerUpsCollected", 12 },
                    { "DamageDealt", 1450 },
                    { "DamageTaken", 680 }
                }
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "计算玩家统计数据失败 - 游戏ID: {GameId}, 玩家ID: {PlayerId}", gameId, playerId);
            return new PlayerStatistics { PlayerId = playerId };
        }
    }

    private async Task<GameStatistics> GenerateGameStatisticsAsync(Guid gameId)
    {
        await Task.CompletedTask; // 避免编译器警告
        
        return new GameStatistics
        {
            TotalDuration = TimeSpan.FromHours(1),
            TotalActions = 850,
            TotalPlayers = 4,
            ActionCounts = new Dictionary<string, int>
            {
                { "Move", 500 },
                { "Attack", 150 },
                { "Collect", 100 },
                { "Skill", 100 }
            },
            CustomStats = new Dictionary<string, object>
            {
                { "MapSize", "Large" },
                { "GameMode", "Territory" },
                { "WeatherEvents", 2 }
            }
        };
    }

    private async Task<List<GameEvent>> GetGameKeyEvents(Guid gameId)
    {
        // 简化的关键事件实现
        await Task.CompletedTask;
        return new List<GameEvent>
        {
            new GameEvent
            {
                PlayerId = null,
                EventType = "GameStart",
                Description = "游戏开始",
                Timestamp = DateTime.UtcNow.AddHours(-1)
            },
            new GameEvent
            {
                PlayerId = null,
                EventType = "GameEnd",
                Description = "游戏结束",
                Timestamp = DateTime.UtcNow
            }
        };
    }

    private async Task<int> CalculatePlayerFinalScore(Guid gameId, Guid playerId)
    {
        // 简化的分数计算
        await Task.CompletedTask;
        return new Random(playerId.GetHashCode()).Next(200, 1200);
    }

    private async Task<double> GetPlayerTerritoryArea(Guid gameId, Guid playerId)
    {
        // 简化的领土面积计算
        await Task.CompletedTask;
        return new Random(playerId.GetHashCode()).NextDouble() * 80.0 + 5.0;
    }

    private async Task<int> GetPlayerKillCount(Guid gameId, Guid playerId)
    {
        // 简化的击杀数计算
        await Task.CompletedTask;
        return new Random(playerId.GetHashCode()).Next(0, 15);
    }

    private async Task<int> GetPlayerDeathCount(Guid gameId, Guid playerId)
    {
        // 简化的死亡数计算
        await Task.CompletedTask;
        return new Random(playerId.GetHashCode()).Next(0, 8);
    }

    #endregion
}
